package com.tyk.bookstore.front.order.service.impl;


import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tyk.bookstore.front.common.core.util.AssertUtil;
import com.tyk.bookstore.front.common.core.util.ObjUtil;
import com.tyk.bookstore.front.order.model.dto.Order4PaymentDto;
import com.tyk.bookstore.front.order.model.dto.Order4PaymentRecordDto;
import com.tyk.bookstore.front.order.model.emume.OrderState;
import com.tyk.bookstore.front.order.model.entity.OrderDetailDo;
import com.tyk.bookstore.front.order.model.entity.OrderDo;
import com.tyk.bookstore.front.order.model.entity.OrderExtraDo;
import com.tyk.bookstore.front.order.model.query.Order4PayNotifyQuery;
import com.tyk.bookstore.front.order.model.result.OrderResultEnum;
import com.tyk.bookstore.front.order.repository.OrderDetailRepository;
import com.tyk.bookstore.front.order.repository.OrderExtraRepository;
import com.tyk.bookstore.front.order.repository.OrderRepository;
import com.tyk.bookstore.front.order.service.OrderApiService;
import com.tyk.bookstore.front.order.util.MapStructOrder;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author tyk
 * @description 订单对内暴露接口
 */
@Service
@RequiredArgsConstructor
public class OrderApiServiceImpl implements OrderApiService {

    private final OrderRepository orderRepository;
    private final OrderExtraRepository orderExtraRepository;
    private final OrderDetailRepository orderDetailRepository;
    private final MapStructOrder mapStructOrder;

    @Override
    public BigDecimal getOrderAmountById(Long orderId, String orderNo, Long memberId) {
        AssertUtil.isTrue(
                orderRepository.exist2Eq(
                        OrderDo::getId, orderId,
                        OrderDo::getMemberId, memberId,
                        OrderDo.class
                ),
                OrderResultEnum.ORDER_NOT_FOUND
        );
        return orderRepository.<BigDecimal>selectSin1Eq(
                OrderDo::getAmount,
                OrderDo::getId, orderId,
                OrderDo.class
        ).getV1();
    }

    @Override
    public void payNotify(Order4PayNotifyQuery query) {

        // 订单存在
        AssertUtil.isTrue(
                orderRepository.exist2Eq(
                        OrderDo::getId, query.getOrderId(),
                        OrderDo::getMemberId, query.getMemberId(),
                        OrderDo.class
                ),
                OrderResultEnum.ORDER_NOT_FOUND
        );


        // 子订单
        List<Long> childIdList = orderRepository.<BigInteger>selectSinList1Eq(
                OrderDo::getId,
                OrderDo::getParentId, query.getOrderId(),
                OrderDo.class
        ).stream().map(it -> it.getV1().longValue()).toList();


        // 更新父订单支付信息
        LocalDateTime now = LocalDateTime.now();
        LambdaUpdateWrapper<OrderExtraDo> w1 = Wrappers.lambdaUpdate();
        w1.set(OrderExtraDo::getPaymentWay, query.getPaymentWay()).
                set(OrderExtraDo::getPaymentTime, now)
                .eq(OrderExtraDo::getOrderId, query.getOrderId());
        orderExtraRepository.update(w1);

        // 更新父订单状态
        LambdaUpdateWrapper<OrderDo> w2 = Wrappers.lambdaUpdate(OrderDo.class);
        w2.eq(OrderDo::getId, query.getOrderId());


        // 无子订单
        if (ObjUtil.isEmpty(childIdList)) {
            // 更新父订单状态
            w2.set(OrderDo::getState, OrderState.WAIT_SEND);
        } else {

            // 删除父订单订单明细
            orderDetailRepository.delete1Eq(
                    OrderDetailDo::getOrderId, query.getOrderId(),
                    OrderDetailDo.class
            );

            // 更新父订单状态
            w2.set(OrderDo::getState, OrderState.SPLIT);

            // 更新子订单支付信息
            LambdaUpdateWrapper<OrderExtraDo> sw1 = Wrappers.lambdaUpdate(OrderExtraDo.class);
            sw1.set(OrderExtraDo::getPaymentWay, query.getPaymentWay())
                    .set(OrderExtraDo::getPaymentTime, now)
                    .in(OrderExtraDo::getOrderId, childIdList);
            orderExtraRepository.update(sw1);

            // 更新子订单状态
            LambdaUpdateWrapper<OrderDo> sw2 = Wrappers.lambdaUpdate(OrderDo.class);
            sw2.set(OrderDo::getState, OrderState.WAIT_SEND)
                    .in(OrderDo::getId, childIdList);
            orderRepository.update(sw2);

        }
        // 更新父订单状态
        orderRepository.update(w2);
    }

    @Override
    public Order4PaymentDto getOrderWaitPay4PaymentDtoById(Long id, Long memberId) {

        Order4PaymentDto dto = orderRepository.selectOrder4PaymentDtoByIdAndMemberId(id, memberId);

        // 订单存在
        AssertUtil.notNull(dto, OrderResultEnum.ORDER_NOT_FOUND);

        // 未支付
        AssertUtil.equal(
                dto.getState(),
                OrderState.WAIT_PAY,
                OrderResultEnum.ORDER_HAS_PAID_OR_CANCEL
        );

        return dto;
    }

    @Override
    public Order4PaymentDto getOrderWaitPay4PaymentDtoById(Long id) {
        // 查询订单信息
        Order4PaymentDto dto = orderRepository.selectOrder4PaymentDtoById(id);
        // 订单存在
        AssertUtil.notNull(dto, OrderResultEnum.ORDER_NOT_FOUND);
        return dto;
    }

    @Override
    public List<Order4PaymentRecordDto> getOrderNoListByIdSet(Set<Long> idSet) {
        if (ObjUtil.isEmpty(idSet)) return new ArrayList<>();
        return orderRepository
                .<BigInteger, String, Long>selectBinList1In(
                        OrderDo::getId, OrderDo::getOrderNo,
                        OrderDo::getId, idSet,
                        OrderDo.class
                ).stream().map(it -> new Order4PaymentRecordDto(it.getV1().longValue(), it.getV2())).toList();
    }
}
